home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
c_news
/
18
/
cnews018.doc
Wrap
Text File
|
1989-12-29
|
74KB
|
2,042 lines
Issue C News 2
=================================================================
THE HEAP by Barry Lynch
=================================================================
The postcards keep coming and we truly appreciate the
support that has been shown over the last two years. This issue
of C News marks the end of Volume 1 of C News. And beginning
with Issue 19, we will start Volume 2 with a few new twists.
(Can't say what they are yet, still working out the details...)
This issue contains another installment of Wayne
Dernoncourt's Beginner's Column. This month Wayne starts
exploring the wondrous world(???) of sort algorithms. Wayne's
article started as a result of a C News staff meeting we had at
a local pizzeria a few months ago. Matter of fact, quite a few
things had their start that night at the pizzeria.
Roy Browning took the time to sit down and write a few
words on his explorations into C++. While I can't claim Roy as
the official C News "C++" guru, we can look forward to his
thoughts as he discovers more about C++. Welcome aboard Roy!
Paul Castle sent us an article on command line parsing
which does a nice job of explaining the concepts of command line
parsing to beginner C programmers.
Jim Singleton - who is beginning to take over C News (grin)
- starts a series on software development in this issue. If you
recall, from a previous issue of C News, Jim and I started
developing an Opus utility to measure my BBS system usage.
Alas, Dan Kozak decided to show off and wrote an AWK script to
accomplish the same thing. Before Jim and I could get started,
Dan was already over the finish line. Well after that
embarrassing episode, Jim threatened Dan with bodily harm if he
showed off again. So I think we can safely assume that Jim's
article will continue in the next issue.
Announcing the Official C News t-shirt and coffee mug. All
contributors to C News get an official C News "Author" t-shirt,
and a coffee mug. Anyone else that wants one will have to
purchase them at cost. Remember that night at the pizzeria?
Well this is one of the ideas that came out of the discussion.
It seems that while Jim Singleton was riding on the steam train
ride at SOGEAST 89, he started talking to Dave Thompson
(Micro-Cornucopia Editor) about C News. It turns out that in
the early days of MicroC, they used to give T-shirts to
contributors instead of money. So after Jim came back from the
SOG, he dropped the idea of a C News T-shirt. Well, I thought
it wasn't a bad idea and now they are available in blue only.
Next year we will pick another colour.
Issue C News 3
Remember the old saying "if you need something done give it
to the busiest person?" Well if you don't, I do and that is the
story of my life these days. Some of you may have noticed that
I do not have as big a part in C News as I used to. It isn't
that I do not want to, but simply that work commitments are
taking all of my free time. However, Jim, Dan and Wayne have
done a great job of getting this issue of C News together. With
their continued support I have no doubt that 1990 will be a
bigger and better year for C News.
Barry
Issue C News 4
=================================================================
MAGAZINE REVIEW - INSIDE TURBO C by Jim Singleton
=================================================================
(NOTE: I initially reviewed "Inside Turbo C" after the first
issue, prior to publishing the review, I received issue number
two. Therefore, reviews of both issues appear here.)
Issue: Volume 1, Number 1 September 1989
Publisher: The Cobb group
P.O. Box 24412
Louisville, KY 40224-9960
"Inside Turbo C" is a new newsletter/magazine, published by
The Cobb Group, Inc. As the title suggests, the subject matter
is Turbo C. At sixteen pages in length, "Inside Turbo C" does
not take too long to read, especially since approximately half
of each issue is source code (seven pages in this issue). While
the articles are clear and concise, they do not attempt to go
into any topic in depth. It will be interesting to see if in
future issues there are articles which span several issues. The
first issue contains articles on interrupts, binary trees, and
fast screen input/output.
As mentioned, each issue contains source code. My biggest
complaint, as far as the appearance of the source code, is that
it is printed with line numbers, which actually makes it look
somewhat confusing. In addition, because of the length of each
issue, none of the articles really explore any topic in any
great depth. The biggest problem is that there are errors in
the source code. I know this often happens in books and
magazines, but here we are talking about a newsletter and I
don't think it should be too hard to check the source code prior
to publication. In fact, one listing is incomplete, it's
missing a number of lines of code.
In addition to the newsletter, subscribers also have access
to Cobb Group Information Services (CGIS) an on-line information
exchange from The Cobb Group. The Basic Service, which is free
to all subscribers, allows the user 15 minutes per day, a back
issues directory, product news, and an information center. A
Premium Service is also available, which allows users to
download source code, no time limit, on-line conferencing, and
the features included with the Basic Service. The Premium
Service is currently available at an "introductory rate" of $30
a year.
Speaking of costs, how much is "Inside Turbo C"? A year's
subscription costs $59. Actually, considering that the cover
price is $7, this represents a savings of $25. The price is the
biggest strike against "Inside Turbo C". It's too expensive for
Issue C News 5
its size, especially since there are a number of other
newsletters and magazines devoted to C. (As a matter of fact,
you're reading one now.)
------------------------------------------------------------
Issue: Volume 1, Number 2 October 1989
I wasn't too impressed with the first issue, of "Inside
Turbo C", so how was issue 2? Don't ask. Once again, the
articles are clearly written. So much for the good news.
Actually, the article on spawning a child process isn't too
bad, nor is the article on conditional compiling. The article
on choosing memory models seems out of place. If the audience
for "Inside Turbo C" is beginners, which is how the article on
spawning a child process is written (along with the introduction
to pointers article and the article on sound generation), this
article is almost useless. All this article really is, is a
definition of each memory model and it takes less than a page to
explain all of them. (A much better article on memory models
appears in issue 11 of the "C News".) If the information in the
Turbo C manuals isn't clear, this isn't going to help much
more.
Well, is the source code any better? The source code for
the article on pointers is long and hard to follow. An article
which is intended as an introduction to pointers should have
clear and concise examples as source code. Also, the one
include file, mcalc.h, makes me think the code is from the
examples provided by Borland when you purchase Turbo C. On the
bright side, it appears that each listing is complete, although
I didn't try all of the listings.
------------------------------------------------------------
NOTE: Since writing the above, I have received a letter from Tim
Landgrave, the Product Manager for Technical Journals for the
Cobb Group, which was sent to all subscribers to "Inside Turbo
C". Although it is a bit of an understatement, he admits that
there are problems with the first two issues of "Inside Turbo
C". Although I didn't catch it (probably because I don't have
the book), one of the examples in the first issue is straight
out of the book "Turbo Algorithms". Also, surprise, surprise,
the program listing for the pointer article is part of the
Borland Microcalc source code. Well, because of these and other
mistakes, all subscriptions to "Inside Turbo C" will begin anew
with the November issue. The first volume is considered trash
("When your new issue arrives, please throw your old ones
away."), and the November issue will be volume II, number 1.
According to Tim, the upcoming issues "will be outstanding in
every way." While that remains to be seen, a review of these
Issue C News 6
upcoming issues of "Inside Turbo C" will appear in an upcoming
issue of the "C News".
Issue C News 7
=================================================================
BEGINNERS CORNER by Wayne Dernoncourt
=================================================================
In the last column I discussed how to use pointers with the
"standard" functions found in almost all implementations
currently in use. This column is going to extend the discussion
of pointers with a discussion of just what pointers are and how
they operate.
Most computers operate with certain absolutes, that is,
there are things that will never change on a specific model or
brand of computer. In the case of an IBM PC compatible
computers, the system clock is at a specific location in memory,
as are the keyboard buffer and disk drive status locations
(there are others, but this is not intended to be a
comprehensive list, just a few examples). As a programmer you
will rarely, if ever, have to deal with these specific locations
-- there are operating system functions which you will use to
interact with these memory locations -- but they do exist.
You can imagine that even if you know the absolute address
of the memory location that you want to access, it would be
difficult to tell a compiler that whenever you access the
variable 'a', you want the computer to access a specific
location. In C this is handled through the mechanisms of
pointers, that is a way for a variable to 'point' to something
else. Since the addresses of the examples (the system clock,
keyboard buffer and disk drive status) are ones that never
change - you can use the C keyword "const" that says that these
addresses will never change and that an error is to be signaled
if your program ever tries to change the address. You can now
set a variable equal to the value pointed at by the pointer.
Let's go back to the example that we started using when
this series of articles first started off, that of finding the
average of 4 numbers. Again we're only going to modify one
module, the one called GETDATA. Everything else is going to
remain the same temporarily.
Here is the code as it was published in the second column of
this series:
Issue C News 8
/* GET_DATA.C */
/* 2. Get any quantity of numbers from a file. To simplify the
problem, we will initially use four numbers hardcoded into
the program. As this column progresses, these
simplifications will be removed. */
float get_data()
{
float sum_x=0.0;
sum_x += 1.0; /* Start here*/
sum_x += 2.0;
sum_x += 3.0;
sum_x += 4.0; /* End here*/
/* Now is the time to return back to the main program. */
return(sum_x);
}
The first order of business is to get rid of the restriction
that we placed at the top of the column. We're going to read in
the four numbers from a file. If there are less than four
numbers present, the program should do what? If there are more
than four numbers, the extras will be ignored. We'll use some
of the techniques developed in the last column on reading a
file. (I've also modified the header at the top of the file,
initially we were going to read the keyboard, now we're using a
file. The same principles apply in both cases.)
I'm going to map out what is going to take place first in
pseudo-code in an attempt to get you to develop good programming
habits.
Basic function declaration - describe what the function is supposed to do
Any #include statements that will be needed
Declare the function - include the pointer variable
Declare memory needed for the file
Declare the variables that be used, the total & the
intermediate variable
(passed from the calling routine)
Open the file for reading, check for error on opening
Setup a loop that will execute until a 'stop value' is
encountered (in this case a negative number)
Read in a number into an intermediate variable
Add the intermediate variable to the total
Increment the counter that indicates the number of
samples read in
Terminate the loop
Decrement the counter (remember we incremented the counter
before we checked the validity of the entry)
Subtract the 'stop value' from the total
Close the file
Issue C News 9
Return the sample size as a passed variable & the total in the
function call
Now for the C code to implement this pseudocode:
/* GET_DATA.C */
/* Read in any quantity numbers from a file - stop on negative numbers */
/* Data passed to this function: address of the variable to hold the */
/* sample size */
/* Data returned from this function: The sum of the series of real */
/* numbers */
#include <stdio.h>
float get_data(int *samp_size_ptr)
{
FILE *in_file; /* declare an area for a file */
float sum_x = 0.0; /* THIS WAS IN THE ABOVE CODE */
float in_val; /* declare an intermediate */
/* variable to be read in */
if ((in_file = fopen ("mydata.dat", "r+t")) == NULL)
{
printf ("Oops, I don\'t see the data file\n");
exit(1);
}
do { /* set up a loop to read in the file */
fscanf (in_file, "%f", &in_val); /* read the file */
sum_x += in_val; /* add the value to the old sum */
(*samp_size_ptr)++; /* increment the counter */
} while (in_val >= 0);
(*samp_size_ptr)--; /* we have to decrement this because */
sum_x -= in_val; /* tried to read in the stop number */
/* and add in the stop number to the sum */
fclose (in_file); /* close the file */
return (sum_x); /* return the sum to the main */
/* program */
}
That's the new version of the GET_DATA routine. There are
a number of unusual things in this function. First is the
function declaration itself. Notice that in the parentheses is
what looks like a variable declaration with an asterisk in front
of it. That is how you declare a pointer. In this specific
case, I've declared that the variable, samp_size_ptr, is in
reality a 'pointer' to a location in memory, and that this
memory location is to contain an integer. The next odd thing
that the keen eyed reader will spot is the backslash 't' in the
printf expression that will be printed if the data file couldn't
Issue C News 10
be opened. There has to be way to put non-printing characters
into a string and it is done with escape sequences that begin
with the backslash. An abbreviated list of these is included
below for quick reference:
Sequence Action
\a Audible bell - this is an ANSI extension
\b Backspace
\f Formfeed
\n New line
\t Horizontal tab
\' Apostrophe or Single quote
\" Double quote - this is an ANSI extension
\? Question mark
The next thing you might ask yourself is why don't we just use
the GET_DATA routine to get the data from the file and return
the value to the calling routine and let it (the calling
routine) decide what to do next (get more data, proceed with the
computations, etc.)? That's logical (it modularizes the code,
etc.), but unfortunately it also defeats one of the main things
that I'm going to show you in the near future, so I'm going to
keep this slightly illogical organization.
You may also notice the '&' in the fscanf function call.
By the way, you may also have noticed that all of the function
oriented to files start with an 'f' (i.e. fopen, fscanf, fclose,
etc.), this is by design, not chance and is part of the ANSI
standard. This symbol tells the compiler to generate
instructions to the computer to pass the address of the variable
to the function instead of the variable itself. This
arrangement is termed "pass-by-reference".
The last thing that I hope you noticed actually consists of
two things, that of (*samp_size_ptr)++ and (*samp_size_ptr)--.
Let's dissect this example carefully to find out what is going
on. First the statement [ *samp_size_ptr ] inside of the
parentheses is executed, this retrieves the value stored at that
location in memory. Then that value is incremented (or
decremented as the case may be), and the value is stored back at
the same location in memory.
The main program file also changes (in three small ways):
Issue C News 11
#include <stdio.h>
float get_data (int *to_samp_size); /* <<--- this changed */
float compute (int samp_size, float x_sum);
void print_results (float average);
main ()
/* This program is to find the mean (average) and standard
deviation of a series of numbers. The numbers will be read in
from the keyboard and printed on the screen. Enter -1 when
finished. Temporarily simplified and reading from a file instead */
/* initialization of variables */
/* 1. Declare all variables needed and initialize them to zero.*/
{
int samp_size=0; /* samp_size: number of variables read in*/
float sum_of_x=0; /* this is the sum of the variables read in*/
float answer;
/* get the data needed by the program */
sum_of_x = get_data(&samp_size); /* <<--- this changed */
/* <<--- deleted a line here */
/* Now compute the answer */
answer = compute(samp_size, sum_of_x);
/* Print the results out */
print_results (answer);
/* Closing the brace on the main routine exits the
program. There are other ways out, but this way will do for
now.*/
}
As I said before, three things have changed in the main
program. The first thing is that the function prototype now
contains a reference to a variable that I've called
'to_samp_size'. Remember that name of the variable isn't
critical (as long as it makes sense to you and helps you
remember what the variable is for). In this case the variable
is to receive an address. The next thing is the '&' in my call
to the function called 'get_data'. This means that I want to
pass not the variable, but the ADDRESS of the variable to the
function. The next line, the line that used to set 'samp_size'
to a quantity is no longer needed.
The other three files (COMPUTE.C, PRINTRES.C & AVERAGE.PRJ) are
included here for completeness. In the file called COMPUTE.C:
Issue C News 12
/* This is the function that determines the average of a bunch
of numbers */
float compute (int n, float xsum)
{
return (xsum/(float)n);
}
In the file called PRINTRES.C:
/* This function prints out the average of the numbers that have
been entered or read in */
void print_results (float average)
{
printf ("\nThe average of the four numbers is:%f\n", average);
return;
}
In the file called AVERAGE.PRJ:
average
get_data
compute
printres
Issue C News 13
=================================================================
TOGGLES AND COMMAND-LINE PARSING by Paul E. Castle II
=================================================================
Every beginners book on C starts out the same way. It
teaches you how to print "Hello, world" on the screen. From
that point on they all follow essentially the same path, the
only real difference being the author's ability to entertain and
teach at the same time. These books teach the basics of the C
language and programming. They give you something upon which to
build. This education is extended and enhanced in the pages of
intermediate and advanced texts. These texts cover topics that
range from random number generators, sort/search algorithms, and
linked lists to complete menuing systems and serial port I/O.
However, there seems to be a gap between the beginner and
intermediate texts, an area of routines and techniques slightly
beyond the beginner's needs and slightly beneath the needs of
the intermediate programmer.
One such case came to my attention while coding a video
tape library program (VTL from this point forward). VTL is a
windowed application. I thought that exploding windows (windows
that seem to explode from the center of the screen out) would be
a nice touch. After a while, however, exploding windows can
cease being an exciting feature and become a distraction. So, I
wanted to give users the ability to toggle the exploding windows
on and off.
I created an integer variable named "explode_active". When
set to 0, exploding windows are inactive. When set to 1, they
are activated. I then added code that was executed whenever
[F10] was pressed.
My first effort was as follows:
if (explode_active == 0)
explode_active = 1;
else
explode_active = 0;
This works. It is simple and obvious. But, I felt is was
more complicated than this simple function need be. I realized
that I could change the "if" statement to read:
"if(!explode_active)" and produce the same result. But there
had to be a better way. I searched my library of C books (which
number in the dozens) and found nothing on toggles. I left the
code as it was and went on to other things.
A few days later, a thought struck me. If I "XOR" 0 and 1,
Issue C News 14
I get 1. And, if I "XOR" 1 and 1, I get 0. That was just the
operation I wanted for the toggle. I rewrote the routine to be:
explode_active = explode_active ^ 1;
Elegant, simple and not that obvious. And not covered in the
texts. So, the answer to how best deal with toggles is as
follows:
1. Create an integer variable - toggle
2. Assume 0 is off, 1 is on
3. toggle = toggle ^ 1
This is something that almost everyone will use and which slips
through the cracks between the beginner and intermediate books.
For another example, read on!
Jim Singleton recently wrote an article on passing and
accessing command line parameters. I'd like to expand on that
article and talk about command line parsing, an important topic
that is neither as simple nor as obvious as toggles and is
rarely found in the texts.
Sooner or later you will want to pass parameters from the
command line to your program. At first, it may be a simple file
name. Later, a source and destination directory. But,
eventually, you will want to use command line parameters as
configuration switches.
This was the case with VTL. Look at the VTL command
syntax:
VTL - Video Tape Library
VTL was written by Paul E. Castle II
Syntax: VTL [-switches]
-b = BIOS screen writing
-c = CGA snow elimination
-h = Display VTL Syntax
-m = Monochrome attributes forced
-x = Exploding windows active
As you can see, VTL can be configured at startup. The command
to start VTL with exploding windows active, monochrome output,
and BIOS I/O would be:
VTL -x -m -b
Jim, in his article, told you how to process this command
Issue C News 15
line. But, what happens when VTL is started in this manner:
VTL -xmb
In the first case, argc indicates 4 parameters and argv
contains pointers to the path to VTL and the strings -x, -m, and
-b. In the second, argc shows 2 parameters and argv contains
pointers to the path to VTL and the string -xmb. To use the
second form, your program must be capable of parsing, or
separating out, the switches contained in the string -xmb.
Look at the code that follows:
parse_cmd_line(int argc,char *argv[])
{
register int i,j;
char *p;
for(i = 1;i < argc;i++) {
p = argv[i];
if (*p == '-' || *p == '/') {
for(j = 1;*(p+j);j++) {
switch(tolower(*(p+j))) {
case 'b':
setvparam(VP_BIOS);
break;
case 'c':
setvparam(VP_CGA);
break;
case 'm':
setvparam(VP_MONO);
break;
case 'x':
explode_active = YES;
break;
default:
error_exit(2); }
}
}
else
error_exit(2); }
}
Notice that the function "parse_cmd_line" is invoked with
the calling function passing argc and argv. This is the same
syntax as described in Jim's article. Next, look at the "for"
statement: "i" is used as an index into argv, "argv[0]" is the
path to the executing program. In this case, we are not
interested in argv[0] so "i" is set to 1. This will be a
pointer to the first parameter (if any) on the command line.
"i<argc" controls the duration of the loop. We will process the
Issue C News 16
command line as long as "i" is less than argc (remember, argc
will contain the number of command line parameters while the
array argv starts at 0. If argc is 3, argv will have entries 0,
1, and 2). And finally, "i" will be incremented with each
iteration.
The next line sets "p" to point to the string pointed to by
argv[i]. This means that, with each iteration of the "for"
loop, "p" will point to each successive command line parameter.
The "if" statement determines if the first character of the
string, pointed to by "p", is a switch character. VTL allows
either the "-" or the "/" to be used as the switch character.
Now, skip down to the end of the "if" statement. The
"else" statement is executed if a valid command line switch
character if not found. In the case of VTL, "error_exit" is a
function to handle error conditions. Based on the value passed,
"error_exit" prints out an error message and terminates
processing. A value of 2, as in this case, will print out the
VTL syntax.
Back to the top. The next statement establishes a second
loop. The loop will be performed until the condition "*(p+j)"
is false. This is the real key to parsing the command line.
Let's analyze this a little. "p" is set to point to the
beginning of a string. If our command line was "VTL -xm -b" and
"i" is equal to 1, "p" is pointing to the "-" in "-xm". The
second loop (or internal loop) begins with "j" equal to 1. This
means that "*(p+j)" is equal to "x". The reason for this is
that "p" is a pointer to type character. The (p+j) is resolved
by incrementing the address, held by "p", by one character
length, or one byte. The "*" operator says to assume the value
of the address pointed to by "(p+j)". This value is "x".
Therefore, the condition "*(p+j)" is true and the switch
statement is processed. In this case, the value "x" triggers
the "case 'x'" and "explode_active" is set to "YES" (which is
defined as a value of 1). Notice that the switch statement
changes the value pointed to by "(p+j)" to a lower case letter.
This allows the user to enter parameters in either upper case or
lower case.
Once the switch statement has completed, the for loop
cycles again. This time "j" is incremented to 2. In the
example above, "*(p+j)" will now resolve to "m". The loop
cycles again, "j" is incremented to 3, and this time "*(p+j)"
resolves to the NUL char or '\0'. This is because all strings,
in C, are terminated by a '\0' character. The '\0' character
has the ASCII value 0, which equates to false. The internal
loop completes and we return to the first loop and increment
"i". On this next pass, "p" is pointing to the string "-b".
The "b" switch will be processed, as above, and we return to the
Issue C News 17
first loop. This time "i" is set to 3, which is equal to argc,
and the function returns to the calling routine.
One final point. Notice that the default "case" in the
switch statement is to execute "error_exit" with a value of 2.
Whenever an invalid parameter is encountered, the switch will
use the default and, in the case of VTL, display the VTL syntax
and terminate processing.
Command line parsing is a powerful and flexible tool in C
programming. It is also one that is seldom found in the texts.
I hope this helps to fill the gap.
Issue C News 18
=================================================================
WHERE'S THAT NUMBER?: A PROJECT IN PROGRAMMING DESIGN
=================================================================
by Jim Singleton
Back a number of issues ago, Barry and I started what was
to be a series of articles on programming design. (See
"Programming Design: OpusGraf a Project, Part I", issue 13, page
12.) We never finished that series, as noted in issue 14,
because Dan whipped out OpusGraf using AWK, as part of his AWK
introduction. Well, here we go again. (This time, I know Dan
is busy, so he will not jump in and finish this series
prematurely.)
This is going to be a series of articles dealing with
software development. Here at the "C News", we have long
thought that a series on programming design would be helpful to
our readers. While not everyone programs in the same style or
manner, most experienced programmers follow roughly the same
development process. This programming project will follow a
project from the idea stage all the way through the design,
coding, and modification of the program. While we will follow
the "correct" programming guidelines, remember that not everyone
writes their programs in the same way and what may be the right
way for one person is not always the right way for you.
For this series of articles, we will be dealing with a
program called PHONENUM, a short program which displays a phone
number for a name entered on the command line. This first
article, will deal with the first six steps of software design:
1. Defining the Problem
2. Defining the Solution
3. Mapping the Solution
4. Coding the Program
5. Debugging the Program
6. Documenting the Program
The seventh (and final) step of software design is updating the
program; which can be a never-ending process, as you think of
things which can be improved. It also involves several of the
other steps. Obviously, since we will just be writing PHONENUM
in this article, we can't really update it just yet.
Issue C News 19
The Idea
(Also known, by the more textbook types, as "Defining the
Problem")
The first part of any programming project is the idea for
the program itself. I don't know of any programmers who sit
down and start writing code with no idea of what they will
write. Ideas for programs can strike anytime, anyplace. For
example, I write them down on a sheet/scrap of paper and then,
at some point, copy the good ones into a loose leaf notebook.
Barry is more organized than I am, he carries a Black
Composition book -- the kind that you find in school bookstores
-- and makes entries as needed. At the end of week, he goes
through the entries and makes a list of the ones that he wants
to work on, and scratches out those that either he has no time
for or were really "banana wackers".
How did I decide to write PHONENUM? Recently, I had to
call Barry, so I had to look up his phone number. Of course, I
had Barry's phone number on my computer; but, to look it up, I
either had to install SideKick or otherwise list it out. I had
been meaning to organize them and write up a short program to
display a phone number. (Everyone knows someone, possibly even
themselves, who keeps meaning to write a short little program to
do something and keeps putting it off, right?) So, I decided I
would finally sit down and write this program and that I would
use it to show the steps involved in developing a program from
start to finish.
Once you decide that it's time to act on one of these
ideas, what do you do?
The Solution
(Oops, let's be formal -- "Defining the Solution".)
Hey, the solution is simple, you say? All I have to do is
write a program look up a phone number. Correct, but that's not
all that goes into the solution. How do I want it displayed?
What should the program look like when it's running? Do I want
windows? As you can see, there are a number of things which go
into the solution of a programming problem.
Well, in the case of this program, PHONENUM, what do "I"
want? (See, this is the advantage of being the author, I can
write the program exactly as I want it.) I want to be able to
call the program with a name as an argument on the command
line. Why? I have a program which will display the location of
area codes throughout the country that way, in addition to one
that will display the location of local telephone exchanges, so
why not one to display phone numbers of the people I deal with?
Issue C News 20
Basically, that's all that there is to the solution of this
problem. I want to be able to type:
PHONENUM lynch
at the system prompt and have Barry's phone number displayed.
Wait a minute, how am I going to add phone numbers to the
list I will be using? Sure, I could maintain a text file with a
text editor or even add a text editor into the program to
maintain the list. Okay, so I will have to have a way to add
names and numbers to my list.
I guess, why I am at it, that I also need to have a warning
displayed to the user if the wrong number of parameters is
entered. ("I" won't forget, but what if some else wants to use
the finished program?)
There are a number of other things I could include in the
finished program, many of which will be revealed as you read
this article, but these three are the only ones necessary for
the basic program. (I am purposely making this program fairly
basic, feel free to make modifications as you see fit.)
To recap, the solution to this problem contains the following
parts:
Command-line interface.
Warning for in correct number of parameters.
Method to add names to the list.
Mapping the Solution
(Also known by the dreaded term "flowchart".)
Okay, I know this section brings up the dreaded F-word.
Come on, let's say it and get it over with. Flowchart. There,
that wasn't too bad, was it? (You know, in this case, I like the
textbook types term, "mapping the solution".)
As most people may have guessed, I don't particularly care
for doing flowcharts. Back when I was learning FORTRAN, I used
to do the flowcharts after I had finished the program and i
would not have done them if I had not been required to turn them
in. These days, however, I do find that mapping out the
solution is a good idea. I don't always map out the solution,
because there are some programs that are straightforward and
don't need it. There are also times I only map out a part of a
solution (normally, a more complex part).
One other thing I don't do anymore, is worry about what
symbols I use. Obviously, if I was preparing this as part of a
class assignment or something, I would; but, for my own
Issue C News 21
programs, boxes are all the symbols I need.
First, let's see an example of an unnecessary flowchart:
+---------+
| BEGIN |
+---------+
|
|
|
+--------------------+
| |
| Display |
| "Hello, world." |
| |
+--------------------+
|
|
|
+---------+
| END |
+---------+
Obviously, in the case of PHONENUM, our flowchart will be a
little more complex. The flowchart is rather self explanatory,
and is contained in the accompanying file, PHONENUM.CHT. (This
way, if you don't want to look at it, you don't have to, just
continue on to the next section.)
Coding the Program
(It's about time!!)
Well, we're finally to the point where we can begin coding
the program. Normally, this would be the section where you give
serious consideration to the language you are going to use; but,
since this is the C NEWS, we're going to do it in C.
Since this is not an article on how to write C programs, I
am not going to go into depth about writing the code. (If you
are new to C, see Wayne's articles elsewhere in this issue,
which will explain how to code in C.)
PHONENUM.C is written in TurboC, version 2.0, although it
should compile with just about any C compiler with few
modifications.
It is not the most elegant solution to our original
problem, but it does work. Why didn't I write a slick,
whiz-bang piece of code? For two reasons, one because I am just
trying to illustrate the steps involved in program design, and
because it gives us something to do in future articles, where we
will enhance and refine the program. (Future articles? That's
Issue C News 22
why "Part 1" included in the title.)
Debugging the Program
(Okay, I'll admit I don't write perfect programs the first time,
but I'm not alone.)
Let's face it, we all make mistakes. (That's why someone
invented debuggers.) When you first compile a program, you're
going to find some mistakes. Some will be little, such as a
missing "}", while others will be harder to figure out. While
debuggers will solve a lot of problems, especially when it comes
to missing "}"s, there are a lot of things they won't tell you.
Among the hardest mistakes to find are mistakes in logic.
I find that once I have corrected syntax and pointer
problems, that running different sets of test data will find
errors. In the case of our PHONENUM, looking up names that are
not there, adding names and then looking them up, etc.
Once you have found all the errors you can find and then
corrected them, it's time to beta test the program. Someone
other than yourself, may find problems you overlooked.
Well, there is a fairly large bug in PHONENUM.C (What,
published code with a bug in it?!) Can you find it? Whoever
mails me the best solution to this bug, by 01 May 1990, will get
a free C NEWS coffee mug. If more than one person sends in the
same solution, a name will be selected out of a hat. (In order
to make it fair for our foreign readers, whose letters will take
longer to reach us.) All solutions must be sent through the
mail, to:
Jim Singleton
P. O. Box 15314
Arlington, VA 22215
No electronic replies, whether in the C Echo, GEnie, etc. will
be eligible.
Documenting the Program
(Oh no, the dreaded "D" word!)
One of the most neglected parts of programming, if not the
most neglected part, is adequately documenting the program. (I
know, you'd rather be writing code.) Adequate documentation is
also one of the most important parts of programming, which is
why it seems strange that it is so often neglected. Perhaps it
is because most programmers would rather just program, rather
than "waste" time documenting the program. (Hey, didn't I
already say this?) Failure to provide proper documentation is
one of the worst habits a programmer can fall into.
Issue C News 23
Proper documentation consists of three parts:
1) the program listing,
2) the technical manual, and
3) the user's manual.
All three of these parts are important and none should be
neglected.
The program listing is just that -- a listing of the
program (which is why we call it a program listing). This
listing should include all the modules, sub-programs, etc. which
make up the program. Everything in the listing should be well
commented. Many programmers have a tendency to comment their
programs rather sparsely, if at all, often because they add the
comments after the program has been completed. The comments
should be included as the program is being written. This
increases the actual time spent coding in the program, but it
saves time later (trust me). It is important to remember, that
each time the program is updated, the comments should be
updated. (If you have ever had to update a piece of uncommented
code, years later, you realize how important it is to add
comments.) You don't have to comment each and every line of
code, just what would not be self explanatory to someone else
reading your code. (Such things as
int count;
or
count++;
are self-explanatory.)
The technical manual should describe the functions and
purposes for each part of the program. It serves as a detailed
description of the program and how the program operates. The
technical manual should be written so that it will be useful
should the program ever have to be modified or updated. If the
programmer prepared a flow chart prior to coding, each part of
the flow chart could serve as a separate section of the
technical manual. The technical manual should contain the
information the programmer used when the program was designed
and coded. Often, the technical manual will be what you have
written down while you have been working on a program (my loose
leaf notebook or Barry's notebook).
Lastly, the users manual describes the operation of the
program from the perspective of the user. This is what most
programmers consider, along with comments embedded in the
program, to be documentation. While this is often the only part
of the documentation which the programmer prepares, it is often
Issue C News 24
of rather poor quality. The user's manual should guide the user
through the operation of the program, describing how it works
and what is required of the user. It should also include sample
sessions or examples, whichever is more appropriate, of the
program in operation. As the user will refer to the users
manual to learn how to use the program, in the case of problems,
and with questions concerning the capabilities of the program,
the users manual should anticipate as many potential questions
and problem areas as possible and address them.
Why spend the time documenting a program? If the program
is for use by others, good documentation can prevent a lot of
questions as to why something doesn't work. If the program
needs to be updated at a future date, good documentation makes
the process a lot easier, whether you do it yourself or have
some one else do it. It can get very frustrating trying to
figure out how a program without comments is supposed to
operate. What if it is only a short program, a utility composed
of only a few lines of code, does it still need all three parts
of the documentation? Of course it does. The technical and
user's manuals may only be a page or so in length, but the
documentation serves the same purpose as it would for a longer
program--it tells how the program operates, how it was written,
why it was written, how to use it, and what each part of the
code does. Proper documentation, a habit for every good
programmer.
Okay, so what does the documentation for PHONENUM look
like? Well, the code is commented, that's one-third of the
documentation out of the way. The technical documentation is
what was written in my notebook (which is essentially in this
article) and the flowchart. Since this program was written for
my own use, there really isn't any need for a users manual.
However, if I were to distribute this program to anyone, I would
write up a short READ.ME file, which would explain how it
works.
Updating the Program.
After you have been using a program for a while, certain
improvements will need to be made, parameters may change, etc.
There may even be an error in the program that escaped detection
earlier. Updating the program is actually a never ending
process, unless the program is either very simple or intended
for limited use. This is where the time spent commenting the
code and writing the documentation comes in handy, because you
won't be spending all your time trying to figure out what each
line of code is supposed to do.
Since we just finished PHONENUM, there really isn't
anything to do in the way of updating it, right? Well.... When
I was writing PHONENUM, I began to think of ways to make it more
Issue C News 25
useful, so subsequent articles in this series will cover adding
a help system to the program, adding a sort routine, adding a
delete utility, windows, and perhaps making PHONENUM a TSR.
(See? I told you they would be revealed before the end of the
program.) If you have an idea on how you'd like to see any of
these implemented or have an idea for a modification I haven't
mentioned, please feel free to contact me here at the C News.
Issue C News 26
=================================================================
SORTING PART 1 by Wayne Dernoncourt
=================================================================
Introduction
The assignment: Write a sort program that will accept
larger files than the MS-DOS sort program.
What an assignment! That has to loose ends to it, so I'm
going to impose some constraints on it.
1. You must be able to use the sort package multiple times
to give the effect of multiple keys, i.e. you want to sort
on the area-code & then sorted on the zip code, but you
want the major sort to be on area-code but sub- sorted by
zip code. [This eliminates some sort algorithms]
2. The sorts will be limited to sorting ASCII data, i.e.
the sort will work on *ANY* file, but will work as if all
of the data is ASCII. Integer and floating point numbers
which are multiple bytes will be interpreted (usually
incorrectly) as ASCII data. EXE and other binary files
won't make any sense for sorting.
General design considerations
Since the assignment was to write a program to handle
larger files than the DOS sort program can handle, let's use the
disk to open some temporary files (this is supposed to handle
LARGE files, but it may not be particularly fast).
How is this going to work, we'll actually sort the keys in
memory using a linked list with references back to a temporary
direct access file.
Let's write some pseudo-code to document how this is
supposed to work:
Open the file to be sorted and find the length of the
longest record (length_longest) and the number of records
(num_of_recs)
Find out how much temporary storage space will be needed in
memory:
mem_needed = (size of key + 4 bytes + 4 bytes + 4
bytes) * num_of_recs
Find out if the amount of storage required is available
Issue C News 27
from the heap? If not complain loudly and abort!!
Find out enough temporary file space is available
disk_needed = length_longest * num_of_recs
If disk_needed is less than that available, complain loudly
and abort!!
Open the file and allocate all of the space needed for the
temporary file.
Everything is okay up too here, should we find out if there
is enough space left over for the new file or just write
over the old one?? No, we have to ask the user if there
isn't enough room left over after we open the random access
file.
Read in the source file sequentially into the temporary
direct access file, copy the key into the corresponding
memory location. Copy the record number into the first 2
four byte locations reserved (direct access record
location, current position of key in list) and the record
number+1 into the last four byte location (position of next
record in list). On the last record, enter a zero for the
next location.
Use a bubble-sort on the key's rearranging only the linked
list items. Since the keys themselves don't change, we can
get rid of the first four byte location that refers to the
direct access record location, it's the same as the
location in the array.
Go back through the linked list in memory and write the new
file using the linked list and the direct access to get the
entire record.
The reason for the bubble-sort is that to implement
secondary keys, the plan is to have the user sort the data using
this package from the deeper keys out (i.e.
tertiarary/secondary/primary, etc.), so we can't rearrange the
relationship that two records that have otherwise equivalent
keys have to one another.
Issue C News 28
=================================================================
C TUTORS: SHAREWARE AND PUBLIC DOMAIN by Jim Singleton
=================================================================
"Does anyone know of a shareware or public domain C
tutor?" How often have you been asked that question or seen it
asked in the FidoNet C Echo? I know I've heard/seen it more
times than I can remember.
The last time I saw that question, I decided to take a look
at what C tutors were available in the public domain and
shareware arenas. Unlike a compiler review, there will be no
benchmarks with this article. The only test I could think of
was having a number of neophytes to C try each one and see which
ones learned C the best, but I didn't feel like waiting for the
results. (Besides, how could I be sure some one wouldn't sneak
out and read a book on me?)
CORONADO ENTERPRISES C TUTOR (Shareware)
This is probably the C tutor which is the most wide spread
on BBS's around the country, usually in two files, C-TUTOR1.ZIP
and C-TUTOR2.ZIP. This tutor consists of a 14 chapter text and
example files. The text introduces C topics by stepping through
these example programs as much as possible. In addition to the
basic topics one would expect to find in such an introductory
tutorial, there is also coverage of such topics as dynamic
allocation and bit manipulation. Because of the differences
between C compilers, a variety of different C compilers are
supported, including Power C, Microsoft C, and TurboC. (This
tutorial can also be found on some BBS' as TCTUTOR1.ZIP and
TCTUTOR2.ZIP.)
TUTOR_C.DOC (Public Domain)
This file, which is normally listed as CTUTOR.ZIP or
TUTOR_C.ZIP, is a text file written by Brian Kernighan.
(Usually this fact is mentioned in the file's description.)
Essentially, this is a condensed version of K&R. There are no
example files, such as those included with the Coronado tutor,
but there are examples in the text itself. If I said you
couldn't learn C from this file, I know some one would prove me
wrong, but I doubt most beginners would get much out of it.
ADVENTURES IN C (Shareware)
This program, normally found as ADV_IN_C.ZIP, is a good
tutorial except that it is not really interactive. It does a
good job of presenting the different topics it covers, but you
don't need a compiler to use the program and there are no sample
Issue C News 29
files included.
Teach-C (Shareware?)
Usually found as TEACH-C.ZIP, Teach-C is an interactive C
tutorial somewhat like Adventures in C. Unlike the latter
tutorial, TEACH-C forces the user to go answer questions while
going through the tutorial. Written by P. J. Ponzo, of the
University of Waterloo, Ontario, Canada, this tutorial uses his
PonzoTUTOR system, which allows the user to interact with the
program. (Instructions are also included to write your own
tutorials using the PonzoTUTOR DISPLAY program.) Halfway
through and at the completion of the tutorial, there is a
comprehensive test for the user. I have also seen this tutorial
as C-TC-RUN.ZIP, which has Turbo C versions of all the examples
included.
So, which tutor is the best? Whichever one teaches you C!
Seriously, it really depends on your experience. If you are
coming to C cold, having just bought a compiler (without a good
tutorial) and no other C books, the Coronado Enterprises tutor
is probably the one for you. The text file by Brian Kernighan
is really only suited to those who need a quick little reference
and don't have K&R. Teach-C and Adventures in C are good for an
introduction before using the Coronado Enterprises tutorial.
Actually, Teach-C is a good review if you are taking a class in
C, as it presents the topics in a very clear manner. Ranked in
order, with the best at the top, these tutorials end up as:
Coronado Enterprises C Tutor
Teach-C
Adventures in C
Tutor_C
Whichever one you choose, remember that actually keying in code
and studying other programmer's code is one of the best ways to
learn C. (That's what puts the Coronado Enterprises C tutor far
ahead of the rest of the ones reviewed here.)
Issue C News 30
=================================================================
MIGRATING FROM C TO C++ by Roy Browning
=================================================================
[Editor's Note: Roy Browning dropped off an article a few weeks
ago on C++ programming here at the C BBS, for possible inclusion
in an issue of C News. Needless to say we were ecstatic, and
look forward to more installments. While I cannot claim Roy as
the C News "C++ Columnist", I can send him a C News "Author"
T-shirt and a coffee mug. Thanks for the support Roy!]
When attempting to acquire new programming skills it is
often expedient to write simple programs that will explore
knowledge recently garnered. The software presented here
exhibits neither a good structured nor object oriented
approach. This is transition code that will hopefully achieve
an acceptable object oriented design when this series is
concluded.
The demonstration code enclosed is a very simple Directory
Lister. A familiar task to most programmers thus new techniques
should readily be distinguishable from the known. A program
that details a couple of C++ techniques while retaining some
misconceptions, a starting place for further exploration.
Classes and Functions
class FileList
A simple class is created to encapsulate the data
obtained from the familiar Dos findfirst/findnext function
calls. The number of files found and structure pointers
are stored as "private" data. The public members included
are the constructor/destructor, a method to return a
specific entry, a member to return the file count, and a
print member to enable the information to be displayed. A
method to return an indexed subgroup of FileNames matching
a passed string has been added.
FileList::FileList()
The constructor has default arguments that can be
superseded if supplied when the instance is created. Dos
interrupt calls are used and storage is dynamically
allocated with the pointer array being reallocated once the
number of files has been determined.
Issue C News 31
FileList::~FileList()
The destructor should be self evident and is called
whenever an instance of a class goes out of "scope".
"Scope" commonly referring to a return from a function in
which the instance was created or when the program is
terminated.
FileList::Print()
Prints information contained in the directory list. A
"for" loop is initialized with the number of files to
display. "form()" is used extensively to properly format
the displayed files.
class FileDate
class FileExt
class FileName
class FileSize
"Classes" that are derived from FileList with full
access to the protected data and the public members. The
syntax that institutes a FileList is in the first line of
the constructor declaration, remarkably powerful. The
sorting methods are invoked whenever an instance of the
class is created.
FileDate::FileDate()
FileExt ::FileExt()
FileName::FileName()
FileSize::FileSize()
This constructor supplies arguments to the FileList
constructor via either the passed data or its own defaults
when the instance is created. Then the appropriate compare
function is passed to "qsort()" creating a directory
listing properly ordered.
FileDate::~FileDate()
FileExt ::~FileExt()
FileName::~FileName()
FileSize::~FileSize()
The destructor is a dummy member relying on the
FileList destructor to do the necessary clean up whenever
the class goes out of scope.
Issue C News 32
Cmp_FileName()
Cmp_FileExt()
Cmp_FileDate()
Cmp_FileSize()
These are simple compare functions that are passed to
the "qsort()" function. Numerical file names are properly
sorted and they will default to a sort by name if all other
data is equivalent. It is imperative that they are
declared as using the "C" calling convention (cdecl) or
else a mangling error will be generated by the compiler.
First_Object()
Second_Object()
Third_Object()
Fourth_Object()
These are test functions that create instances of
class FileList passing the different Sort methods. They
are constructed as separate functions so the destructor
will be called on return. Otherwise memory would quickly
become exhausted (64k) with large directory listings.
main()
Calls the four test functions then creates an instance
of FileSize. Tests the FileName_Match member and displays
all the matching directory entries. Then selects a
specific element in the directory array and displays the
file's name. Reports the total number of files matching
the attributes, prints a final message and terminates.
This documentation is intentionally terse for the source
code itself is the best example of the logic followed. If you
wish to supply alternative demonstrations you may contact me via
the following means:
Roy Browning
FidoNet 1:106/506
MCI Mail 184-6847
The Fulcrum's Edge (713)350-6284
Issue C News 33
=================================================================
ARTICLE SUBMISSION STANDARDS
=================================================================
All articles, reviews and letters to editor should be
submitted as ASCII files. Please do not format the text in any
way (no hyphenation, justification, indentation, etc.) since we
use Proff to format C News. Proff takes care of the
justification, footnotes and headers.
You can send in your article on a diskette to the C BBS, or
upload it to the C BBS. See "How to Contact us here at C News"
for more information.
Barry
Issue C News 34
=================================================================
HOW TO GET HOLD OF US HERE AT CNEWS
=================================================================
The primary address for C News is as follows:
C News
% BCL Limited
P.O. Box 9162
McLean, VA 22102
USA
The primary electronic address for C News is the C BBS:
C BBS
1-703-644-6478
2400,8,N,1 23hrs a day.
1:109/307 in Fidonet.
The secondary electronic address for C News is:
MCI Mail: BCL Limited
Barry
Issue C News 1
*--------------------------------------------------------------*
| C NEWS - International C Electronic Newsletter/Journal |
| "Dedicated to the Art of C Programming" |
| |
| Founded 12/27/87 |
*--------------------------------------------------------------*
Table of Contents
THE HEAP by Barry Lynch ................................ 2
MAGAZINE REVIEW - INSIDE TURBO C by Jim Singleton.......... 4
BEGINNERS CORNER by Wayne Dernoncourt .................. 7
TOGGLES AND COMMAND-LINE PARSING by Paul E. Castle II...... 13
WHERE'S THAT NUMBER?: A PROJECT IN PROGRAMMING DESIGN ..... 18
SORTING PART 1 by Wayne Dernoncourt ..................... 26
C TUTORS: SHAREWARE AND PUBLIC DOMAIN by Jim Singleton..... 28
MIGRATING FROM C TO C++ by Roy Browning ................... 30
ARTICLE SUBMISSION STANDARDS ......................... 33
HOW TO GET HOLD OF US HERE AT CNEWS........................ 34
"C News" is an Electronic Journal published by the C BBS in
Burke, VA on a monthly basis. The subject for C News is the C
programming language, as well as any derivatives like C++.
All readers are encouraged to submit articles, reviews, or
comments for submission. C News is freely distributed, but can
not be sold for a profit, or cannot have a charge assessed to
cover distribution costs. All articles, and reviews become the
property of C News and cannot be included in other
publications without written permission from the C News
Editorial Staff. To do so is in direct violation of the C News
License agreement. Copies of which are available from the C
BBS. This publication is Copyrighted under U.S. Copyright
Law.